<?php

namespace catchAdmin\externalGoods\service;

use catchAdmin\externalGoods\model\Category;
use catchAdmin\externalGoods\model\Goods as externalGoodsModel;
use catchAdmin\externalGoods\model\GoodsAttribute;
use catchAdmin\externalGoods\model\GoodsRule;
use catchAdmin\externalGoods\model\TenantGoods as tenantGoodsModel;
use catchAdmin\externalGoods\model\GoodsRule as externalGoodsRuleModel;
use catchAdmin\externalGoods\model\GoodsAttribute as externalGoodsAttribute;
use catchAdmin\externalGoods\model\TenantGoodsAttr;
use catchAdmin\externalGoods\model\TenantGoodsAttr as tenantGoodsAttrModel;
use catchAdmin\externalGoods\model\TenantGoodsRule as tenantGoodsRuleModel;
use catchAdmin\externalGoods\model\TenantPricePrecent;
use catcher\CatchAuth;
use catcher\CatchResponse;
use houniao\api\v1\Goods;
use think\Exception;
use think\facade\Db;
use think\facade\Log;

class TenantGoodsService
{

    protected $user;
    protected $percent = 1.29;

    public function __construct()
    {
//        $user = (new CatchAuth())->user();
//        $this->user = $user;
    }

    //添加选择的商品
    public function addSelect($param,$tenant_id = 0){
        if($tenant_id !== 0){
            $user = (new \catchAdmin\permissions\model\Users())->find($tenant_id);
        }else{
            $user = (new CatchAuth())->user();
        }
        $this->user  = $user;
        $this->percent = (float) ($user['qekj_tenant_goods_precent'] ?? 1.1);

        $tenantGoodsModel = new tenantGoodsModel();
        $tenantGoodsAttrModel = new tenantGoodsAttrModel();
        $tenantGoodsRuleModel = new tenantGoodsRuleModel();
        $externalGoodsModel = new externalGoodsModel();
        $externalGoodsAttrModel = new externalGoodsAttribute();
        $externalGoodsRuleModel = new externalGoodsRuleModel();

        if(!is_array($param)){
            $param = [$param];
        }

        //获取资源池商品数据
        $externalGoodsResult = $externalGoodsModel
            ->withoutField('created_at,updated_at,deleted_at,tenant_id,creator_id')
            ->where('id','in',$param)->select()->toArray();

        //获取已经添加的记录
//        $selfGoodsIds = $tenantGoodsModel->where('id','in',$param)->column('syst_goods_id');
        $selfGoodsIds = $tenantGoodsModel
            ->where('tenant_id',$tenant_id)
            ->where('syst_goods_id','in',$param)
            ->column('syst_goods_id');

        foreach ($externalGoodsResult as $key => &$value){
            if(in_array($value['id'],$selfGoodsIds)){//判断是否已经添加
                unset($externalGoodsResult[$key]);
                continue;
            }
            $value['syst_goods_id'] = $value['id'];
            $value['tenant_id'] = $user['tenant_id'];
            $value['creator_id'] = $user['id'];
//            if($user['tenant_id'] == '10043'){
//                $value['price'] = round($value['cost_price'] * $this->percent);
//            }
            $value['price'] = round($value['cost_price'] * $this->percent);

            unset($value['id']);
        }

        if(0 == count($externalGoodsResult)){
            return CatchResponse::success([],'success');
        }

        Db::startTrans();
        try {

            $needGoodsIDs = array_column($externalGoodsResult,'syst_goods_id');
            //获取资源池商品属性数据
            $externalGoodsAttrResult = $externalGoodsAttrModel
                ->withoutField('created_at,updated_at,deleted_at,tenant_id,creator_id')
                ->where('goods_id','in',$needGoodsIDs)->select()->toArray();

            //添加商品
            $saveAllResult =  $tenantGoodsModel->saveAll($externalGoodsResult);

            $saveAllPk =  array_column($saveAllResult->toArray(),null,'syst_goods_id');

            foreach ($externalGoodsAttrResult as $key => &$value){
                $value['syst_goods_attr_id'] = $value['id'];
                $value['tenant_id'] = $user['tenant_id'];
                $value['creator_id'] = $user['id'];
                $value['goods_id'] = $saveAllPk[$value['goods_id']]['id'];
                unset($value['id']);
            }
            //获取资源池商品规格数据
            $externalGoodsRuleResult = $externalGoodsRuleModel
                ->withoutField('created_at,updated_at,deleted_at,tenant_id,creator_id')
                ->where('goods_id','in',$needGoodsIDs)->select()->toArray();

            foreach ($externalGoodsRuleResult as $key => &$value){
                $value['syst_goods_rule_id'] = $value['id'];
                $value['tenant_id'] = $user['tenant_id'];
                $value['creator_id'] = $user['id'];
                $value['goods_id'] = $saveAllPk[$value['goods_id']]['id'];
                unset($value['id']);

                $value['sku_price'] = round($value['cost_price'] * $this->percent);
//                if($user['tenant_id'] == '10043'){
//                    $value['sku_price'] = round($value['cost_price'] * $this->percent);
//                }
            }

            //添加属性
            $tenantGoodsAttrModel->saveAll($externalGoodsAttrResult);
            //添加规格
            $tenantGoodsRuleModel->saveAll($externalGoodsRuleResult);

            Db::commit();
            return CatchResponse::success([],'success');
        } catch (\Exception $exception) {
            Db::rollback();
//            dd($exception->getMessage());
            return CatchResponse::fail('选品添加失败' . $exception->getMessage());
        }

    }

    //渠道商添加商品
    public function createGoods($param,$mode){
        //检验参数

        //添加商品
        Db::startTrans();
        try {
            $this->goodsTemplate($param,$mode);

            Db::commit();
        } catch (\Exception $exception) {
            Db::rollback();
            return CatchResponse::fail('添加失败' . $exception->getMessage());
        }

        return CatchResponse::success([],'success');
    }

    //渠道商修改商品
    public function editGoods($param,$mode){
        //检验参数

        Db::startTrans();
        try {
            $this->goodsTemplate($param,$mode);

            Db::commit();
        } catch (\Exception $exception) {
            Db::rollback();
            return CatchResponse::fail('修改失败' . $exception->getMessage());
        }
        return CatchResponse::success([],'success');
    }

    //处理商品业务
    public function goodsTemplate($param,$mode){
        //校验参数
        $this->checkParam($param,$mode);

        //处理商品基础数据
        $goods =  $this->dealBase($param,$mode);

        //处理商品属性
        $param['goods_spu'] = $goods->goods_spu;
        $param['id'] = $goods->id;

        if(2 == $param['spec']){
            $this->dealAttr($param,$mode);

            //处理商品规格
            $this->dealRule($param,$mode);
        }
        //处理商品其他东西
    }

    //商品参数
    public function checkParam($param,$mode){
        if(1 == $param['spec']){//单规格
            if (empty($param['price']) || $param['price'] < 0) {
                throw new Exception("请输入大于等于0的售价");
            }

            if ($param['stock'] == '' || $param['stock'] < 0) {
                throw new Exception("请输入大于等于0的库存");
            }
        }elseif(2 == $param['spec']){//多规格
            if(empty($param['goods_attr']) || empty($param['goods_rule'])){
                throw new Exception("规格没有传值");
            }
        }
    }

    private function dealBase($param,$mode){
        $goodsModel = new tenantGoodsModel;

        $goods_img = $param['goods_img'];
        $param['goods_img'] = array_shift($goods_img);//主图
        $param['goods_slideshow_img'] = json_encode($goods_img);//轮播图

        //分类ID
        //$param['category_id'] = (new Category)->where('id',$param['category_id'])->value('cate_id');

        if($mode == 'edit'){
            unset($param['goods_spu']);
            unset($param['supplier_id']);
            $goodsModel = $goodsModel->where('id',$param['id'])->find();
            $goodsModel->save($param);
        }else{
            $param['goods_spu'] = $param['tenant_id'] . time() . mt_rand(1000,9999);
            $param['create_mode'] = 1;//后台创建
            $param['supplier_id'] = $param['tenant_id'];
            $goodsModel->storeBy($param);
        }

        return $goodsModel;
    }

    private function dealAttr($param){
        $goods_attr = json_decode(json_encode($param['goods_attr']),true);

        //属性的新增、删除、修改
        $goodsAttributeModel = new TenantGoodsAttr;

        //获取数据库中已存在的所有属性
        $existAttrs = $goodsAttributeModel->where('goods_id', $param['id'])->select()->toArray();
        
        //构造属性的唯一标识(name:attribute_name)
        $getAttrKey = function($attr) {
            return $attr['name'] . ':' . $attr['attribute_name'];
        };
        
        //获取现有属性的唯一标识
        $existAttrKeys = array_map($getAttrKey, $existAttrs);
        
        //获取新属性的唯一标识
        $newAttrKeys = array_map($getAttrKey, $goods_attr);
        
        //计算需要删除的属性
        $toDelete = array_diff($existAttrKeys, $newAttrKeys);
        
        //计算需要新增的属性
        $toInsert = array_diff($newAttrKeys, $existAttrKeys);
        
        //计算需要更新的属性
        $toUpdate = array_intersect($newAttrKeys, $existAttrKeys);

        //构建existAttrs的查找索引
        $existAttrsMap = [];
        foreach ($existAttrs as $attr) {
            $key = $getAttrKey($attr);
            $existAttrsMap[$key] = $attr;
        }
        
        $insert = [];

        Db::startTrans();
        try {
            foreach ($goods_attr as $value) {
                $attrKey = $getAttrKey($value);
                
                if (in_array($attrKey, $toInsert)) {
                    // 新增的属性
                    $value['attribute_id'] = date("YmdHis") . mt_rand(1000, 9999);
                    $value['goods_id'] = $param['id'];
                    $value['goods_spu'] = $param['goods_spu'];
                    $value['tenant_id'] = $param['tenant_id'];
                    $value['creator_id'] = $param['creator_id'];
                    $insert[] = $value;
                } elseif (in_array($attrKey, $toUpdate)) {
                    // 更新的属性
                    $existAttr = $existAttrsMap[$attrKey];
                    // 保持原有的attribute_id
                    $value['attribute_id'] = $existAttr['attribute_id'];
                    $goodsAttributeModel->updateBy($existAttr['id'], $value);
                }
            }

            // 批量新增
            if (!empty($insert)) {
                $goodsAttributeModel->saveAll($insert);
            }

            // 批量删除
            if (!empty($toDelete)) {
                $deleteIds = [];
                foreach ($toDelete as $key) {
                    $deleteIds[] = $existAttrsMap[$key]['id'];
                }
                $goodsAttributeModel->deleteBy($deleteIds);
            }

            Db::commit();
            return true;
        } catch (\Exception $exception) {
            Db::rollback();
            throw new Exception(json_encode($exception->getMessage()));
        }
    }

    private function dealRule($param){
        $goods_rule = json_decode(json_encode($param['goods_rule']),true);

        //规格的新增、删除、修改
        $goodsRuleModel = new tenantGoodsRuleModel;
        $goodsAttrModel = new tenantGoodsAttrModel;
        $goodsModel = new tenantGoodsModel;

        //获取数据库中已存在的所有规格
        $existRules = $goodsRuleModel->where('goods_id', $param['id'])->select()->toArray();
        $existSkuNames = array_column($existRules, 'sku_name');
        
        //获取前端传来的所有规格名
        $newSkuNames = array_column($goods_rule, 'sku_name');
        
        //计算需要删除的规格(在数据库中存在但不在新数据中的)
        $toDelete = array_diff($existSkuNames, $newSkuNames);
        
        //计算需要新增的规格(在新数据中存在但不在数据库中的)
        $toInsert = array_diff($newSkuNames, $existSkuNames);
        
        //计算需要更新的规格(新旧数据中都存在的)
        $toUpdate = array_intersect($newSkuNames, $existSkuNames);

        //构建existRules的查找索引
        $existRulesMap = array_column($existRules, null, 'sku_name');
        
        $insert = [];
        $goodsStock = 0;
        $goodsPriceMap = [];

        Db::startTrans();
        try {
            // 处理每个规格
            foreach ($goods_rule as $value) {
                $goodsStock += $value['sku_stock'];
                $goodsPriceMap[] = $value['sku_price'];
                
                if (in_array($value['sku_name'], $toInsert)) {
                    // 新增的规格
                    $value['goods_sku'] = date("YmdHis") . mt_rand(1000, 9999);
                    $value['goods_spu'] = $param['goods_spu'];
                    $value['goods_id'] = $param['id'];

                    $new_sku_name = explode(';', $value['sku_name']);
                    $sku_name_arr = [];
                    
                    foreach ($new_sku_name as $v) {
                        $temp = explode(':', $v);
                        $sku_name_arr[] = $goodsAttrModel
                            ->field('attribute_id,attribute_name')
                            ->where([
                                'goods_id' => $param['id'],
                                'name' => $temp[0],
                                'attribute_name' => $temp[1]
                            ])
                            ->find();
                    }

                    $value['spec_sku'] = implode('_', array_column($sku_name_arr, 'attribute_id'));
                    $value['sku_attribute_id'] = json_encode(array_column($sku_name_arr, 'attribute_id'));
                    $value['sku_attribute_name'] = json_encode(array_column($sku_name_arr, 'attribute_name'));
                    $value['tenant_id'] = $param['tenant_id'];
                    $value['creator_id'] = $param['creator_id'];
                    
                    $insert[] = $value;
                } elseif (in_array($value['sku_name'], $toUpdate)) {
                    // 更新的规格
                    $existRule = $existRulesMap[$value['sku_name']];
                    $goodsRuleModel->updateBy($existRule['id'], $value);
                }
            }

            // 批量新增
            if (!empty($insert)) {
                $goodsRuleModel->saveAll($insert);
            }

            // 批量删除
            if (!empty($toDelete)) {
                $deleteIds = array_column(array_intersect_key($existRulesMap, array_flip($toDelete)), 'id');
                $goodsRuleModel->deleteBy($deleteIds);
            }

            // 更新商品总库存和最低价格
            if ($param['spec'] == 2) {
                $goodsParam = [
                    'stock' => $goodsStock,
                    'price' => min($goodsPriceMap),
                ];
                $goodsModel->updateBy($param['id'], $goodsParam);
            }

            Db::commit();
            return true;
        } catch (\Exception $exception) {
            Db::rollback();
            throw new Exception(json_encode($exception->getMessage()));
        }
    }


    protected function writeGoods($product,$server,$tenant_id,$cover=0,$percent= 1.29){
        //$percent = 1.29;
        foreach ($product as $key => &$value){

            if(empty($value['photo'])){
                continue;
            }
            //SNO 不能为空
            if(NULL === $value['type']) continue;

            $goods_name = $value['goods_name'];
            $goods_pk_id = $value['id'];
            $value['tenant_id'] = $tenant_id;
            unset($product[$key]['id']);

            //上传图片到服务器---------开始
//                $new_photo = [];
//                foreach ($value['photo'] as $k => $v){
//                    $upload = $this->syncImage($v);
//                    if(!$upload) continue;
//                    $new_photo[] = $upload['url'];
//                }
//                $value['photo'] = implode(',',$new_photo);
//                print_r(  $goods_name.'----------图片上传成功'. PHP_EOL);

            //上传图片到服务器---------结束

            $is_exist =  Db::connect($server)->table('db_product')
                ->where([
                    'ifshow'=>1,
                    'prod'=>$value['prod'],
                    'tenant_id'=>$tenant_id
                ])
                ->find();

            //存在且忽略跳过。
            if($is_exist && 0 == $cover) continue;

            if($is_exist){
                    Db::connect($server)->table('db_product')->where('pid',$is_exist['pid'])->update($value);
            }else{
                $insertGetId =  Db::connect($server)->table('db_product')->insertGetId($value);
            }


            $goods_spu = $value['prod'];

            //-----------商品属性记录
            $goods_attr = (new GoodsAttribute)->field('name,attribute_name')->where('goods_id',$goods_pk_id)->select()->toArray();
            $attr_arr = [];
            foreach ($goods_attr as $attr_v){
                if(!in_array($attr_v['attribute_name'],$attr_arr)) {
                    $attr_arr[$attr_v['name']][] = $attr_v['attribute_name'];
                }
            }
            //处理属性
            foreach ($attr_arr as $k => $v){
                $remote_attr = Db::connect($server)->table('db_property')
                    ->field('sid,cbval')
                    ->where([
                        'SNO'=> $value['type'],//分类 = 跨进电商
                        'tradeid'=> $tenant_id,
                        'property'=>$k
                    ])->find();

                if($remote_attr){//存在属性名
                    $cbvalArr = explode('$',$remote_attr['cbval']);

                    foreach ($v as $kk){
                        if(!in_array($kk , $cbvalArr)){//属性值不存在的话，
                            $cbvalArr[] = $kk;
                        }
                    }
                    $cbval = implode('$',$cbvalArr);
                    //更新
                    Db::connect($server)->table('db_property')->where('sid',$remote_attr['sid'])->update([
                        'cbval'=>$cbval
                    ]);

                }else{
                    $cbval = implode('$',$v);
                    //新增
                    $res =  Db::connect($server)->table('db_property')->insert([
                        'SNO'=>$value['type'],
                        'property'=>$k,
                        'tradeid'=>$tenant_id,
                        'cbval'=>$cbval,
                        'english'=>'',
                        'value'=>'',
                        'if'=>'否'
                    ]);

                    if(!$res){
                        throw new Exception('添加property失败');
//                        Log::error('property' . json_encode([
//                                'SNO'=>$value['type'],
//                                'property'=>$k,
//                                'tradeid'=>$tenant_id,
//                                'cbval'=>$cbval,
//                                'english'=>'',
//                                'value'=>'',
//                                'if'=>'否'
//                            ]));
                    }

                }
            }

            //-----------商品规格
            //查询规格记录
            $goods_rule = (new GoodsRule)->field('sku_name,sku_price,sku_stock,cost_price,goods_sku')->where('goods_id',$goods_pk_id)->select()->toArray();


            $rulesArr = [];
            foreach ($goods_rule as $gr_v){
                $rule_name_arr =[];
                $rule_value_arr = [];
                $sku_list = explode(';',$gr_v['sku_name']);

                //dd($sku_list);

                foreach ($sku_list as $sku){
                    $rule_name_arr[] = explode(':',$sku)[0];
                    $rule_value_arr[] = explode(':',$sku)[1];
                }

                //查询 pr_id
                $sid_arr =  Db::connect($server)->table('db_property')
                    ->where([
                        ['property','in',$rule_name_arr],
                        ['SNO','=',$value['type']],
                        ['tradeid','=',$tenant_id]
                    ])
                    ->column('sid');

                $trade_type_id = externalGoodsModel::getTradeTypeIdBySpu($goods_spu);

                //获取商户各种贸易类型成本价
                $tenant_percent = TenantPricePrecent::getPercentByTid($tenant_id,$trade_type_id,'qekj');
                $cost_percent = $tenant_percent['cost_percent'];
                $price_percent = $tenant_percent['price_percent'];

                $rulesArr[] =   [
                    'pid'=>$goods_spu,
                    'pr_id'=>implode(',',$sid_arr),
                    'pr_name'=>implode(',',$rule_name_arr),
                    'suk_val'=>implode(',',$rule_value_arr),
                    'suk_num'=>$gr_v['sku_stock'],
                    'suk_price'=> round($gr_v['cost_price'] * $price_percent),
                    'cost_price'=> round($gr_v['cost_price'] * $cost_percent),
                    'if_stock'=>1,
                    'tradeid'=>$tenant_id,
                    'sku_id'=>$gr_v['goods_sku']
                ];
            }
            /**
             * 删除之前所有规格
             */

            Db::connect($server)->table('db_pro_attr')->where([
                'tradeid'=>$tenant_id,
                'pid'=>$goods_spu
            ])->delete();
            Db::connect($server)->table('db_pro_attr')->limit(100)->insertAll($rulesArr);
//                break;
        }
    }


    public function syncGoodsToQekj($goods_spus,$cover=0,$tenant_id=1111,$percent= 1.29,$category_id=null){
        $server = "mysql_df_remote";
//        $tenant_id = 1103;
        //$SNO = '05';
        $goods_order = 28;
        //$percent = 1.29;

        $where = [
            ['goods_spu','in',$goods_spus]
        ];
//        $where = [];

        $total = (new externalGoodsModel)->where($where)->count();

        //dd($total);

        for($i =1;$i<= (int)ceil($total / 100);$i++){

            $product = (new externalGoodsModel())->field('
            id,
            goods_spu as prod,
            cost_price as formerprice,
            goods_name,
            goods_img,
            goods_slideshow_img,
            stock,
            description as detail_img,
            barcode,
            cost_price as final_cost,
            origin_name as product_area,
            category_id,trade_type_id,is_sale
            ')
                ->where($where)
                ->page($i,100)
                ->order('id asc')
                ->select()
                ->each(function(&$item) use ($tenant_id,$goods_order,$server,$percent,$cover,$category_id){

                    //获取商户各种贸易类型成本价
                    $tenant_percent = TenantPricePrecent::getPercentByTid($tenant_id,$item['trade_type_id'],'qekj');
                    $cost_percent = $tenant_percent['cost_percent'];
                    $price_percent = $tenant_percent['price_percent'];


                    $item['formerprice'] = round($item['formerprice'] * $price_percent);
                    $item['final_cost'] = round($item['final_cost'] * $cost_percent);
                    $item['tenant_id'] = $tenant_id;
                    $item['photo'] = array_merge([$item['goods_img']], json_decode($item['goods_slideshow_img'],true));
                    $item['photo'] = implode(',',$item['photo']);
                    unset($item['goods_img']);
                    unset($item['goods_slideshow_img']);
                    $item['description'] = '';

                    //设置默认属性 15 = 跨境电商

                    $category_arr = (new Category)->field('level,name')->where('id',$item['category_id'])->find();

                    if($category_arr){
                        $category_arr = $category_arr->toArray();
                        $sss_sno =  Db::connect($server)->table('posap')->where(
                            [
                                'tradeid'=> $tenant_id,
                                'LAYER'=> $category_arr['level'] ,
                                'SNAME'=>$category_arr['name'],
                            ]
                        )->value('SNO');
                        if(!empty($category_id)){
                            $item['type'] = $category_id;
                        }else{
                            $item['type'] = $sss_sno;
                        }
                    }else{
                        $item['type'] = NULL;
                    }

                    //跨境
                    if(in_array($item['trade_type_id'] ,[1,4,5])){
                        $item['is_cross_border'] = 1;
                    }

                    //上下架
                    if($item['is_sale'] == 1){
                        $item['is_show'] = 0;
                    }else{
                        $item['is_show'] = 1;
                    }

                    //商品来源
                    $item['source'] = 1;//候鸟 1

                    //$item['type'] = $sss_sno;

                    $item['orders'] = $goods_order;
                    unset($item['category_id']);
                    unset($item['trade_type_id']);
                    unset($item['is_sale']);
                })
                ->toArray();

            // dd($product);

            Db::startTrans();
            try {
                $this->writeGoods($product,$server,$tenant_id,$cover,$percent);
                // 提交事务
                Db::commit();

            } catch (\Exception $e) {
                // 回滚事务
                Db::rollback();
                Log::error('上传商品失败' . $e->getMessage());
                throw new Exception('失败' . json_encode($e->getTrace()));
                //dd('失败' . $e->getMessage());
            }
        }
        //$db2 = Db::connect('mysql_df')->table('db_product')->count();
    }

    public function getTenantGoodsSkuPrice($tenant_id,$goods_spu,$sku_id){
        $cost_price = (new GoodsRule)->where([
            'goods_sku'=>$sku_id,
            'goods_spu'=>$goods_spu
        ])->order('id','desc')->value('cost_price');

        //拿到合作商折扣
        $percent = (new \catchAdmin\permissions\model\Users())->where(['id'=>$tenant_id])->value('qekj_tenant_goods_precent');

        return round($cost_price * $percent);
    }
}